OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #if V8_TARGET_ARCH_X64 | 5 #if V8_TARGET_ARCH_X64 |
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 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
127 DCHECK(!IsGeneratorFunction(info->literal()->kind()) || locals_count == 0); | 127 DCHECK(!IsGeneratorFunction(info->literal()->kind()) || locals_count == 0); |
128 if (locals_count == 1) { | 128 if (locals_count == 1) { |
129 __ PushRoot(Heap::kUndefinedValueRootIndex); | 129 __ PushRoot(Heap::kUndefinedValueRootIndex); |
130 } else if (locals_count > 1) { | 130 } else if (locals_count > 1) { |
131 if (locals_count >= 128) { | 131 if (locals_count >= 128) { |
132 Label ok; | 132 Label ok; |
133 __ movp(rcx, rsp); | 133 __ movp(rcx, rsp); |
134 __ subp(rcx, Immediate(locals_count * kPointerSize)); | 134 __ subp(rcx, Immediate(locals_count * kPointerSize)); |
135 __ CompareRoot(rcx, Heap::kRealStackLimitRootIndex); | 135 __ CompareRoot(rcx, Heap::kRealStackLimitRootIndex); |
136 __ j(above_equal, &ok, Label::kNear); | 136 __ j(above_equal, &ok, Label::kNear); |
137 __ CallRuntime(Runtime::kThrowStackOverflow, 0); | 137 __ CallRuntime(Runtime::kThrowStackOverflow); |
138 __ bind(&ok); | 138 __ bind(&ok); |
139 } | 139 } |
140 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); | 140 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); |
141 const int kMaxPushes = 32; | 141 const int kMaxPushes = 32; |
142 if (locals_count >= kMaxPushes) { | 142 if (locals_count >= kMaxPushes) { |
143 int loop_iterations = locals_count / kMaxPushes; | 143 int loop_iterations = locals_count / kMaxPushes; |
144 __ movp(rcx, Immediate(loop_iterations)); | 144 __ movp(rcx, Immediate(loop_iterations)); |
145 Label loop_header; | 145 Label loop_header; |
146 __ bind(&loop_header); | 146 __ bind(&loop_header); |
147 // Do pushes. | 147 // Do pushes. |
(...skipping 16 matching lines...) Expand all Loading... |
164 | 164 |
165 // Possibly allocate a local context. | 165 // Possibly allocate a local context. |
166 if (info->scope()->num_heap_slots() > 0) { | 166 if (info->scope()->num_heap_slots() > 0) { |
167 Comment cmnt(masm_, "[ Allocate context"); | 167 Comment cmnt(masm_, "[ Allocate context"); |
168 bool need_write_barrier = true; | 168 bool need_write_barrier = true; |
169 int slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; | 169 int slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; |
170 // Argument to NewContext is the function, which is still in rdi. | 170 // Argument to NewContext is the function, which is still in rdi. |
171 if (info->scope()->is_script_scope()) { | 171 if (info->scope()->is_script_scope()) { |
172 __ Push(rdi); | 172 __ Push(rdi); |
173 __ Push(info->scope()->GetScopeInfo(info->isolate())); | 173 __ Push(info->scope()->GetScopeInfo(info->isolate())); |
174 __ CallRuntime(Runtime::kNewScriptContext, 2); | 174 __ CallRuntime(Runtime::kNewScriptContext); |
175 PrepareForBailoutForId(BailoutId::ScriptContext(), TOS_REG); | 175 PrepareForBailoutForId(BailoutId::ScriptContext(), TOS_REG); |
176 // The new target value is not used, clobbering is safe. | 176 // The new target value is not used, clobbering is safe. |
177 DCHECK_NULL(info->scope()->new_target_var()); | 177 DCHECK_NULL(info->scope()->new_target_var()); |
178 } else { | 178 } else { |
179 if (info->scope()->new_target_var() != nullptr) { | 179 if (info->scope()->new_target_var() != nullptr) { |
180 __ Push(rdx); // Preserve new target. | 180 __ Push(rdx); // Preserve new target. |
181 } | 181 } |
182 if (slots <= FastNewContextStub::kMaximumSlots) { | 182 if (slots <= FastNewContextStub::kMaximumSlots) { |
183 FastNewContextStub stub(isolate(), slots); | 183 FastNewContextStub stub(isolate(), slots); |
184 __ CallStub(&stub); | 184 __ CallStub(&stub); |
185 // Result of FastNewContextStub is always in new space. | 185 // Result of FastNewContextStub is always in new space. |
186 need_write_barrier = false; | 186 need_write_barrier = false; |
187 } else { | 187 } else { |
188 __ Push(rdi); | 188 __ Push(rdi); |
189 __ CallRuntime(Runtime::kNewFunctionContext, 1); | 189 __ CallRuntime(Runtime::kNewFunctionContext); |
190 } | 190 } |
191 if (info->scope()->new_target_var() != nullptr) { | 191 if (info->scope()->new_target_var() != nullptr) { |
192 __ Pop(rdx); // Restore new target. | 192 __ Pop(rdx); // Restore new target. |
193 } | 193 } |
194 } | 194 } |
195 function_in_register = false; | 195 function_in_register = false; |
196 // Context is returned in rax. It replaces the context passed to us. | 196 // Context is returned in rax. It replaces the context passed to us. |
197 // It's saved in the stack and kept live in rsi. | 197 // It's saved in the stack and kept live in rsi. |
198 __ movp(rsi, rax); | 198 __ movp(rsi, rax); |
199 __ movp(Operand(rbp, StandardFrameConstants::kContextOffset), rax); | 199 __ movp(Operand(rbp, StandardFrameConstants::kContextOffset), rax); |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
297 bool is_unmapped = is_strict(language_mode()) || !has_simple_parameters(); | 297 bool is_unmapped = is_strict(language_mode()) || !has_simple_parameters(); |
298 ArgumentsAccessStub::Type type = ArgumentsAccessStub::ComputeType( | 298 ArgumentsAccessStub::Type type = ArgumentsAccessStub::ComputeType( |
299 is_unmapped, literal()->has_duplicate_parameters()); | 299 is_unmapped, literal()->has_duplicate_parameters()); |
300 ArgumentsAccessStub stub(isolate(), type); | 300 ArgumentsAccessStub stub(isolate(), type); |
301 __ CallStub(&stub); | 301 __ CallStub(&stub); |
302 | 302 |
303 SetVar(arguments, rax, rbx, rdx); | 303 SetVar(arguments, rax, rbx, rdx); |
304 } | 304 } |
305 | 305 |
306 if (FLAG_trace) { | 306 if (FLAG_trace) { |
307 __ CallRuntime(Runtime::kTraceEnter, 0); | 307 __ CallRuntime(Runtime::kTraceEnter); |
308 } | 308 } |
309 | 309 |
310 // Visit the declarations and body unless there is an illegal | 310 // Visit the declarations and body unless there is an illegal |
311 // redeclaration. | 311 // redeclaration. |
312 if (scope()->HasIllegalRedeclaration()) { | 312 if (scope()->HasIllegalRedeclaration()) { |
313 Comment cmnt(masm_, "[ Declarations"); | 313 Comment cmnt(masm_, "[ Declarations"); |
314 VisitForEffect(scope()->GetIllegalRedeclaration()); | 314 VisitForEffect(scope()->GetIllegalRedeclaration()); |
315 | 315 |
316 } else { | 316 } else { |
317 PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS); | 317 PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS); |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
407 | 407 |
408 | 408 |
409 void FullCodeGenerator::EmitReturnSequence() { | 409 void FullCodeGenerator::EmitReturnSequence() { |
410 Comment cmnt(masm_, "[ Return sequence"); | 410 Comment cmnt(masm_, "[ Return sequence"); |
411 if (return_label_.is_bound()) { | 411 if (return_label_.is_bound()) { |
412 __ jmp(&return_label_); | 412 __ jmp(&return_label_); |
413 } else { | 413 } else { |
414 __ bind(&return_label_); | 414 __ bind(&return_label_); |
415 if (FLAG_trace) { | 415 if (FLAG_trace) { |
416 __ Push(rax); | 416 __ Push(rax); |
417 __ CallRuntime(Runtime::kTraceExit, 1); | 417 __ CallRuntime(Runtime::kTraceExit); |
418 } | 418 } |
419 // Pretend that the exit is a backwards jump to the entry. | 419 // Pretend that the exit is a backwards jump to the entry. |
420 int weight = 1; | 420 int weight = 1; |
421 if (info_->ShouldSelfOptimize()) { | 421 if (info_->ShouldSelfOptimize()) { |
422 weight = FLAG_interrupt_budget / FLAG_self_opt_count; | 422 weight = FLAG_interrupt_budget / FLAG_self_opt_count; |
423 } else { | 423 } else { |
424 int distance = masm_->pc_offset(); | 424 int distance = masm_->pc_offset(); |
425 weight = Min(kMaxBackEdgeWeight, | 425 weight = Min(kMaxBackEdgeWeight, |
426 Max(1, distance / kCodeSizeMultiplier)); | 426 Max(1, distance / kCodeSizeMultiplier)); |
427 } | 427 } |
(...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
801 // Push initial value, if any. | 801 // Push initial value, if any. |
802 // Note: For variables we must not push an initial value (such as | 802 // Note: For variables we must not push an initial value (such as |
803 // 'undefined') because we may have a (legal) redeclaration and we | 803 // 'undefined') because we may have a (legal) redeclaration and we |
804 // must not destroy the current value. | 804 // must not destroy the current value. |
805 if (hole_init) { | 805 if (hole_init) { |
806 __ PushRoot(Heap::kTheHoleValueRootIndex); | 806 __ PushRoot(Heap::kTheHoleValueRootIndex); |
807 } else { | 807 } else { |
808 __ Push(Smi::FromInt(0)); // Indicates no initial value. | 808 __ Push(Smi::FromInt(0)); // Indicates no initial value. |
809 } | 809 } |
810 __ Push(Smi::FromInt(variable->DeclarationPropertyAttributes())); | 810 __ Push(Smi::FromInt(variable->DeclarationPropertyAttributes())); |
811 __ CallRuntime(Runtime::kDeclareLookupSlot, 3); | 811 __ CallRuntime(Runtime::kDeclareLookupSlot); |
812 break; | 812 break; |
813 } | 813 } |
814 } | 814 } |
815 } | 815 } |
816 | 816 |
817 | 817 |
818 void FullCodeGenerator::VisitFunctionDeclaration( | 818 void FullCodeGenerator::VisitFunctionDeclaration( |
819 FunctionDeclaration* declaration) { | 819 FunctionDeclaration* declaration) { |
820 VariableProxy* proxy = declaration->proxy(); | 820 VariableProxy* proxy = declaration->proxy(); |
821 Variable* variable = proxy->var(); | 821 Variable* variable = proxy->var(); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
855 OMIT_SMI_CHECK); | 855 OMIT_SMI_CHECK); |
856 PrepareForBailoutForId(proxy->id(), NO_REGISTERS); | 856 PrepareForBailoutForId(proxy->id(), NO_REGISTERS); |
857 break; | 857 break; |
858 } | 858 } |
859 | 859 |
860 case VariableLocation::LOOKUP: { | 860 case VariableLocation::LOOKUP: { |
861 Comment cmnt(masm_, "[ FunctionDeclaration"); | 861 Comment cmnt(masm_, "[ FunctionDeclaration"); |
862 __ Push(variable->name()); | 862 __ Push(variable->name()); |
863 VisitForStackValue(declaration->fun()); | 863 VisitForStackValue(declaration->fun()); |
864 __ Push(Smi::FromInt(variable->DeclarationPropertyAttributes())); | 864 __ Push(Smi::FromInt(variable->DeclarationPropertyAttributes())); |
865 __ CallRuntime(Runtime::kDeclareLookupSlot, 3); | 865 __ CallRuntime(Runtime::kDeclareLookupSlot); |
866 break; | 866 break; |
867 } | 867 } |
868 } | 868 } |
869 } | 869 } |
870 | 870 |
871 | 871 |
872 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { | 872 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { |
873 // Call the runtime to declare the globals. | 873 // Call the runtime to declare the globals. |
874 __ Push(pairs); | 874 __ Push(pairs); |
875 __ Push(Smi::FromInt(DeclareGlobalsFlags())); | 875 __ Push(Smi::FromInt(DeclareGlobalsFlags())); |
876 __ CallRuntime(Runtime::kDeclareGlobals, 2); | 876 __ CallRuntime(Runtime::kDeclareGlobals); |
877 // Return value is ignored. | 877 // Return value is ignored. |
878 } | 878 } |
879 | 879 |
880 | 880 |
881 void FullCodeGenerator::DeclareModules(Handle<FixedArray> descriptions) { | 881 void FullCodeGenerator::DeclareModules(Handle<FixedArray> descriptions) { |
882 // Call the runtime to declare the modules. | 882 // Call the runtime to declare the modules. |
883 __ Push(descriptions); | 883 __ Push(descriptions); |
884 __ CallRuntime(Runtime::kDeclareModules, 1); | 884 __ CallRuntime(Runtime::kDeclareModules); |
885 // Return value is ignored. | 885 // Return value is ignored. |
886 } | 886 } |
887 | 887 |
888 | 888 |
889 void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { | 889 void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { |
890 Comment cmnt(masm_, "[ SwitchStatement"); | 890 Comment cmnt(masm_, "[ SwitchStatement"); |
891 Breakable nested_statement(this, stmt); | 891 Breakable nested_statement(this, stmt); |
892 SetStatementPosition(stmt); | 892 SetStatementPosition(stmt); |
893 | 893 |
894 // Keep the switch value on the stack until a case matches. | 894 // Keep the switch value on the stack until a case matches. |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1028 | 1028 |
1029 // The enum cache is valid. Load the map of the object being | 1029 // The enum cache is valid. Load the map of the object being |
1030 // iterated over and use the cache for the iteration. | 1030 // iterated over and use the cache for the iteration. |
1031 Label use_cache; | 1031 Label use_cache; |
1032 __ movp(rax, FieldOperand(rax, HeapObject::kMapOffset)); | 1032 __ movp(rax, FieldOperand(rax, HeapObject::kMapOffset)); |
1033 __ jmp(&use_cache, Label::kNear); | 1033 __ jmp(&use_cache, Label::kNear); |
1034 | 1034 |
1035 // Get the set of properties to enumerate. | 1035 // Get the set of properties to enumerate. |
1036 __ bind(&call_runtime); | 1036 __ bind(&call_runtime); |
1037 __ Push(rax); // Duplicate the enumerable object on the stack. | 1037 __ Push(rax); // Duplicate the enumerable object on the stack. |
1038 __ CallRuntime(Runtime::kGetPropertyNamesFast, 1); | 1038 __ CallRuntime(Runtime::kGetPropertyNamesFast); |
1039 PrepareForBailoutForId(stmt->EnumId(), TOS_REG); | 1039 PrepareForBailoutForId(stmt->EnumId(), TOS_REG); |
1040 | 1040 |
1041 // If we got a map from the runtime call, we can do a fast | 1041 // If we got a map from the runtime call, we can do a fast |
1042 // modification check. Otherwise, we got a fixed array, and we have | 1042 // modification check. Otherwise, we got a fixed array, and we have |
1043 // to do a slow check. | 1043 // to do a slow check. |
1044 Label fixed_array; | 1044 Label fixed_array; |
1045 __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset), | 1045 __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset), |
1046 Heap::kMetaMapRootIndex); | 1046 Heap::kMetaMapRootIndex); |
1047 __ j(not_equal, &fixed_array); | 1047 __ j(not_equal, &fixed_array); |
1048 | 1048 |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1110 Label update_each; | 1110 Label update_each; |
1111 __ movp(rcx, Operand(rsp, 4 * kPointerSize)); | 1111 __ movp(rcx, Operand(rsp, 4 * kPointerSize)); |
1112 __ cmpp(rdx, FieldOperand(rcx, HeapObject::kMapOffset)); | 1112 __ cmpp(rdx, FieldOperand(rcx, HeapObject::kMapOffset)); |
1113 __ j(equal, &update_each, Label::kNear); | 1113 __ j(equal, &update_each, Label::kNear); |
1114 | 1114 |
1115 // Convert the entry to a string or null if it isn't a property | 1115 // Convert the entry to a string or null if it isn't a property |
1116 // anymore. If the property has been removed while iterating, we | 1116 // anymore. If the property has been removed while iterating, we |
1117 // just skip it. | 1117 // just skip it. |
1118 __ Push(rcx); // Enumerable. | 1118 __ Push(rcx); // Enumerable. |
1119 __ Push(rbx); // Current entry. | 1119 __ Push(rbx); // Current entry. |
1120 __ CallRuntime(Runtime::kForInFilter, 2); | 1120 __ CallRuntime(Runtime::kForInFilter); |
1121 PrepareForBailoutForId(stmt->FilterId(), TOS_REG); | 1121 PrepareForBailoutForId(stmt->FilterId(), TOS_REG); |
1122 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); | 1122 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); |
1123 __ j(equal, loop_statement.continue_label()); | 1123 __ j(equal, loop_statement.continue_label()); |
1124 __ movp(rbx, rax); | 1124 __ movp(rbx, rax); |
1125 | 1125 |
1126 // Update the 'each' property or variable from the possibly filtered | 1126 // Update the 'each' property or variable from the possibly filtered |
1127 // entry in register rbx. | 1127 // entry in register rbx. |
1128 __ bind(&update_each); | 1128 __ bind(&update_each); |
1129 __ movp(result_register(), rbx); | 1129 __ movp(result_register(), rbx); |
1130 // Perform the assignment as if via '='. | 1130 // Perform the assignment as if via '='. |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1168 if (!FLAG_always_opt && | 1168 if (!FLAG_always_opt && |
1169 !FLAG_prepare_always_opt && | 1169 !FLAG_prepare_always_opt && |
1170 !pretenure && | 1170 !pretenure && |
1171 scope()->is_function_scope() && | 1171 scope()->is_function_scope() && |
1172 info->num_literals() == 0) { | 1172 info->num_literals() == 0) { |
1173 FastNewClosureStub stub(isolate(), info->language_mode(), info->kind()); | 1173 FastNewClosureStub stub(isolate(), info->language_mode(), info->kind()); |
1174 __ Move(rbx, info); | 1174 __ Move(rbx, info); |
1175 __ CallStub(&stub); | 1175 __ CallStub(&stub); |
1176 } else { | 1176 } else { |
1177 __ Push(info); | 1177 __ Push(info); |
1178 __ CallRuntime( | 1178 __ CallRuntime(pretenure ? Runtime::kNewClosure_Tenured |
1179 pretenure ? Runtime::kNewClosure_Tenured : Runtime::kNewClosure, 1); | 1179 : Runtime::kNewClosure); |
1180 } | 1180 } |
1181 context()->Plug(rax); | 1181 context()->Plug(rax); |
1182 } | 1182 } |
1183 | 1183 |
1184 | 1184 |
1185 void FullCodeGenerator::EmitSetHomeObject(Expression* initializer, int offset, | 1185 void FullCodeGenerator::EmitSetHomeObject(Expression* initializer, int offset, |
1186 FeedbackVectorSlot slot) { | 1186 FeedbackVectorSlot slot) { |
1187 DCHECK(NeedsHomeObject(initializer)); | 1187 DCHECK(NeedsHomeObject(initializer)); |
1188 __ movp(StoreDescriptor::ReceiverRegister(), Operand(rsp, 0)); | 1188 __ movp(StoreDescriptor::ReceiverRegister(), Operand(rsp, 0)); |
1189 __ Move(StoreDescriptor::NameRegister(), | 1189 __ Move(StoreDescriptor::NameRegister(), |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1308 Variable* local = var->local_if_not_shadowed(); | 1308 Variable* local = var->local_if_not_shadowed(); |
1309 __ movp(rax, ContextSlotOperandCheckExtensions(local, slow)); | 1309 __ movp(rax, ContextSlotOperandCheckExtensions(local, slow)); |
1310 if (local->mode() == LET || local->mode() == CONST || | 1310 if (local->mode() == LET || local->mode() == CONST || |
1311 local->mode() == CONST_LEGACY) { | 1311 local->mode() == CONST_LEGACY) { |
1312 __ CompareRoot(rax, Heap::kTheHoleValueRootIndex); | 1312 __ CompareRoot(rax, Heap::kTheHoleValueRootIndex); |
1313 __ j(not_equal, done); | 1313 __ j(not_equal, done); |
1314 if (local->mode() == CONST_LEGACY) { | 1314 if (local->mode() == CONST_LEGACY) { |
1315 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); | 1315 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); |
1316 } else { // LET || CONST | 1316 } else { // LET || CONST |
1317 __ Push(var->name()); | 1317 __ Push(var->name()); |
1318 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 1318 __ CallRuntime(Runtime::kThrowReferenceError); |
1319 } | 1319 } |
1320 } | 1320 } |
1321 __ jmp(done); | 1321 __ jmp(done); |
1322 } | 1322 } |
1323 } | 1323 } |
1324 | 1324 |
1325 | 1325 |
1326 void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy, | 1326 void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy, |
1327 TypeofMode typeof_mode) { | 1327 TypeofMode typeof_mode) { |
1328 Variable* var = proxy->var(); | 1328 Variable* var = proxy->var(); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1363 if (NeedsHoleCheckForLoad(proxy)) { | 1363 if (NeedsHoleCheckForLoad(proxy)) { |
1364 // Let and const need a read barrier. | 1364 // Let and const need a read barrier. |
1365 Label done; | 1365 Label done; |
1366 GetVar(rax, var); | 1366 GetVar(rax, var); |
1367 __ CompareRoot(rax, Heap::kTheHoleValueRootIndex); | 1367 __ CompareRoot(rax, Heap::kTheHoleValueRootIndex); |
1368 __ j(not_equal, &done, Label::kNear); | 1368 __ j(not_equal, &done, Label::kNear); |
1369 if (var->mode() == LET || var->mode() == CONST) { | 1369 if (var->mode() == LET || var->mode() == CONST) { |
1370 // Throw a reference error when using an uninitialized let/const | 1370 // Throw a reference error when using an uninitialized let/const |
1371 // binding in harmony mode. | 1371 // binding in harmony mode. |
1372 __ Push(var->name()); | 1372 __ Push(var->name()); |
1373 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 1373 __ CallRuntime(Runtime::kThrowReferenceError); |
1374 } else { | 1374 } else { |
1375 // Uninitialized legacy const bindings are unholed. | 1375 // Uninitialized legacy const bindings are unholed. |
1376 DCHECK(var->mode() == CONST_LEGACY); | 1376 DCHECK(var->mode() == CONST_LEGACY); |
1377 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); | 1377 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); |
1378 } | 1378 } |
1379 __ bind(&done); | 1379 __ bind(&done); |
1380 context()->Plug(rax); | 1380 context()->Plug(rax); |
1381 break; | 1381 break; |
1382 } | 1382 } |
1383 context()->Plug(var); | 1383 context()->Plug(var); |
1384 break; | 1384 break; |
1385 } | 1385 } |
1386 | 1386 |
1387 case VariableLocation::LOOKUP: { | 1387 case VariableLocation::LOOKUP: { |
1388 Comment cmnt(masm_, "[ Lookup slot"); | 1388 Comment cmnt(masm_, "[ Lookup slot"); |
1389 Label done, slow; | 1389 Label done, slow; |
1390 // Generate code for loading from variables potentially shadowed | 1390 // Generate code for loading from variables potentially shadowed |
1391 // by eval-introduced variables. | 1391 // by eval-introduced variables. |
1392 EmitDynamicLookupFastCase(proxy, typeof_mode, &slow, &done); | 1392 EmitDynamicLookupFastCase(proxy, typeof_mode, &slow, &done); |
1393 __ bind(&slow); | 1393 __ bind(&slow); |
1394 __ Push(rsi); // Context. | 1394 __ Push(rsi); // Context. |
1395 __ Push(var->name()); | 1395 __ Push(var->name()); |
1396 Runtime::FunctionId function_id = | 1396 Runtime::FunctionId function_id = |
1397 typeof_mode == NOT_INSIDE_TYPEOF | 1397 typeof_mode == NOT_INSIDE_TYPEOF |
1398 ? Runtime::kLoadLookupSlot | 1398 ? Runtime::kLoadLookupSlot |
1399 : Runtime::kLoadLookupSlotNoReferenceError; | 1399 : Runtime::kLoadLookupSlotNoReferenceError; |
1400 __ CallRuntime(function_id, 2); | 1400 __ CallRuntime(function_id); |
1401 __ bind(&done); | 1401 __ bind(&done); |
1402 context()->Plug(rax); | 1402 context()->Plug(rax); |
1403 break; | 1403 break; |
1404 } | 1404 } |
1405 } | 1405 } |
1406 } | 1406 } |
1407 | 1407 |
1408 | 1408 |
1409 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { | 1409 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { |
1410 Comment cmnt(masm_, "[ RegExpLiteral"); | 1410 Comment cmnt(masm_, "[ RegExpLiteral"); |
(...skipping 26 matching lines...) Expand all Loading... |
1437 void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { | 1437 void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { |
1438 Comment cmnt(masm_, "[ ObjectLiteral"); | 1438 Comment cmnt(masm_, "[ ObjectLiteral"); |
1439 | 1439 |
1440 Handle<FixedArray> constant_properties = expr->constant_properties(); | 1440 Handle<FixedArray> constant_properties = expr->constant_properties(); |
1441 int flags = expr->ComputeFlags(); | 1441 int flags = expr->ComputeFlags(); |
1442 if (MustCreateObjectLiteralWithRuntime(expr)) { | 1442 if (MustCreateObjectLiteralWithRuntime(expr)) { |
1443 __ Push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); | 1443 __ Push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); |
1444 __ Push(Smi::FromInt(expr->literal_index())); | 1444 __ Push(Smi::FromInt(expr->literal_index())); |
1445 __ Push(constant_properties); | 1445 __ Push(constant_properties); |
1446 __ Push(Smi::FromInt(flags)); | 1446 __ Push(Smi::FromInt(flags)); |
1447 __ CallRuntime(Runtime::kCreateObjectLiteral, 4); | 1447 __ CallRuntime(Runtime::kCreateObjectLiteral); |
1448 } else { | 1448 } else { |
1449 __ movp(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); | 1449 __ movp(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); |
1450 __ Move(rbx, Smi::FromInt(expr->literal_index())); | 1450 __ Move(rbx, Smi::FromInt(expr->literal_index())); |
1451 __ Move(rcx, constant_properties); | 1451 __ Move(rcx, constant_properties); |
1452 __ Move(rdx, Smi::FromInt(flags)); | 1452 __ Move(rdx, Smi::FromInt(flags)); |
1453 FastCloneShallowObjectStub stub(isolate(), expr->properties_count()); | 1453 FastCloneShallowObjectStub stub(isolate(), expr->properties_count()); |
1454 __ CallStub(&stub); | 1454 __ CallStub(&stub); |
1455 } | 1455 } |
1456 PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG); | 1456 PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG); |
1457 | 1457 |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1500 break; | 1500 break; |
1501 } | 1501 } |
1502 __ Push(Operand(rsp, 0)); // Duplicate receiver. | 1502 __ Push(Operand(rsp, 0)); // Duplicate receiver. |
1503 VisitForStackValue(key); | 1503 VisitForStackValue(key); |
1504 VisitForStackValue(value); | 1504 VisitForStackValue(value); |
1505 if (property->emit_store()) { | 1505 if (property->emit_store()) { |
1506 if (NeedsHomeObject(value)) { | 1506 if (NeedsHomeObject(value)) { |
1507 EmitSetHomeObject(value, 2, property->GetSlot()); | 1507 EmitSetHomeObject(value, 2, property->GetSlot()); |
1508 } | 1508 } |
1509 __ Push(Smi::FromInt(SLOPPY)); // Language mode | 1509 __ Push(Smi::FromInt(SLOPPY)); // Language mode |
1510 __ CallRuntime(Runtime::kSetProperty, 4); | 1510 __ CallRuntime(Runtime::kSetProperty); |
1511 } else { | 1511 } else { |
1512 __ Drop(3); | 1512 __ Drop(3); |
1513 } | 1513 } |
1514 break; | 1514 break; |
1515 case ObjectLiteral::Property::PROTOTYPE: | 1515 case ObjectLiteral::Property::PROTOTYPE: |
1516 __ Push(Operand(rsp, 0)); // Duplicate receiver. | 1516 __ Push(Operand(rsp, 0)); // Duplicate receiver. |
1517 VisitForStackValue(value); | 1517 VisitForStackValue(value); |
1518 DCHECK(property->emit_store()); | 1518 DCHECK(property->emit_store()); |
1519 __ CallRuntime(Runtime::kInternalSetPrototype, 2); | 1519 __ CallRuntime(Runtime::kInternalSetPrototype); |
1520 break; | 1520 break; |
1521 case ObjectLiteral::Property::GETTER: | 1521 case ObjectLiteral::Property::GETTER: |
1522 if (property->emit_store()) { | 1522 if (property->emit_store()) { |
1523 accessor_table.lookup(key)->second->getter = property; | 1523 accessor_table.lookup(key)->second->getter = property; |
1524 } | 1524 } |
1525 break; | 1525 break; |
1526 case ObjectLiteral::Property::SETTER: | 1526 case ObjectLiteral::Property::SETTER: |
1527 if (property->emit_store()) { | 1527 if (property->emit_store()) { |
1528 accessor_table.lookup(key)->second->setter = property; | 1528 accessor_table.lookup(key)->second->setter = property; |
1529 } | 1529 } |
1530 break; | 1530 break; |
1531 } | 1531 } |
1532 } | 1532 } |
1533 | 1533 |
1534 // Emit code to define accessors, using only a single call to the runtime for | 1534 // Emit code to define accessors, using only a single call to the runtime for |
1535 // each pair of corresponding getters and setters. | 1535 // each pair of corresponding getters and setters. |
1536 for (AccessorTable::Iterator it = accessor_table.begin(); | 1536 for (AccessorTable::Iterator it = accessor_table.begin(); |
1537 it != accessor_table.end(); | 1537 it != accessor_table.end(); |
1538 ++it) { | 1538 ++it) { |
1539 __ Push(Operand(rsp, 0)); // Duplicate receiver. | 1539 __ Push(Operand(rsp, 0)); // Duplicate receiver. |
1540 VisitForStackValue(it->first); | 1540 VisitForStackValue(it->first); |
1541 EmitAccessor(it->second->getter); | 1541 EmitAccessor(it->second->getter); |
1542 EmitAccessor(it->second->setter); | 1542 EmitAccessor(it->second->setter); |
1543 __ Push(Smi::FromInt(NONE)); | 1543 __ Push(Smi::FromInt(NONE)); |
1544 __ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5); | 1544 __ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked); |
1545 } | 1545 } |
1546 | 1546 |
1547 // Object literals have two parts. The "static" part on the left contains no | 1547 // Object literals have two parts. The "static" part on the left contains no |
1548 // computed property names, and so we can compute its map ahead of time; see | 1548 // computed property names, and so we can compute its map ahead of time; see |
1549 // runtime.cc::CreateObjectLiteralBoilerplate. The second "dynamic" part | 1549 // runtime.cc::CreateObjectLiteralBoilerplate. The second "dynamic" part |
1550 // starts with the first computed property name, and continues with all | 1550 // starts with the first computed property name, and continues with all |
1551 // properties to its right. All the code from above initializes the static | 1551 // properties to its right. All the code from above initializes the static |
1552 // component of the object literal, and arranges for the map of the result to | 1552 // component of the object literal, and arranges for the map of the result to |
1553 // reflect the static order in which the keys appear. For the dynamic | 1553 // reflect the static order in which the keys appear. For the dynamic |
1554 // properties, we compile them into a series of "SetOwnProperty" runtime | 1554 // properties, we compile them into a series of "SetOwnProperty" runtime |
1555 // calls. This will preserve insertion order. | 1555 // calls. This will preserve insertion order. |
1556 for (; property_index < expr->properties()->length(); property_index++) { | 1556 for (; property_index < expr->properties()->length(); property_index++) { |
1557 ObjectLiteral::Property* property = expr->properties()->at(property_index); | 1557 ObjectLiteral::Property* property = expr->properties()->at(property_index); |
1558 | 1558 |
1559 Expression* value = property->value(); | 1559 Expression* value = property->value(); |
1560 if (!result_saved) { | 1560 if (!result_saved) { |
1561 __ Push(rax); // Save result on the stack | 1561 __ Push(rax); // Save result on the stack |
1562 result_saved = true; | 1562 result_saved = true; |
1563 } | 1563 } |
1564 | 1564 |
1565 __ Push(Operand(rsp, 0)); // Duplicate receiver. | 1565 __ Push(Operand(rsp, 0)); // Duplicate receiver. |
1566 | 1566 |
1567 if (property->kind() == ObjectLiteral::Property::PROTOTYPE) { | 1567 if (property->kind() == ObjectLiteral::Property::PROTOTYPE) { |
1568 DCHECK(!property->is_computed_name()); | 1568 DCHECK(!property->is_computed_name()); |
1569 VisitForStackValue(value); | 1569 VisitForStackValue(value); |
1570 DCHECK(property->emit_store()); | 1570 DCHECK(property->emit_store()); |
1571 __ CallRuntime(Runtime::kInternalSetPrototype, 2); | 1571 __ CallRuntime(Runtime::kInternalSetPrototype); |
1572 } else { | 1572 } else { |
1573 EmitPropertyKey(property, expr->GetIdForProperty(property_index)); | 1573 EmitPropertyKey(property, expr->GetIdForProperty(property_index)); |
1574 VisitForStackValue(value); | 1574 VisitForStackValue(value); |
1575 if (NeedsHomeObject(value)) { | 1575 if (NeedsHomeObject(value)) { |
1576 EmitSetHomeObject(value, 2, property->GetSlot()); | 1576 EmitSetHomeObject(value, 2, property->GetSlot()); |
1577 } | 1577 } |
1578 | 1578 |
1579 switch (property->kind()) { | 1579 switch (property->kind()) { |
1580 case ObjectLiteral::Property::CONSTANT: | 1580 case ObjectLiteral::Property::CONSTANT: |
1581 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 1581 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
1582 case ObjectLiteral::Property::COMPUTED: | 1582 case ObjectLiteral::Property::COMPUTED: |
1583 if (property->emit_store()) { | 1583 if (property->emit_store()) { |
1584 __ Push(Smi::FromInt(NONE)); | 1584 __ Push(Smi::FromInt(NONE)); |
1585 __ CallRuntime(Runtime::kDefineDataPropertyUnchecked, 4); | 1585 __ CallRuntime(Runtime::kDefineDataPropertyUnchecked); |
1586 } else { | 1586 } else { |
1587 __ Drop(3); | 1587 __ Drop(3); |
1588 } | 1588 } |
1589 break; | 1589 break; |
1590 | 1590 |
1591 case ObjectLiteral::Property::PROTOTYPE: | 1591 case ObjectLiteral::Property::PROTOTYPE: |
1592 UNREACHABLE(); | 1592 UNREACHABLE(); |
1593 break; | 1593 break; |
1594 | 1594 |
1595 case ObjectLiteral::Property::GETTER: | 1595 case ObjectLiteral::Property::GETTER: |
1596 __ Push(Smi::FromInt(NONE)); | 1596 __ Push(Smi::FromInt(NONE)); |
1597 __ CallRuntime(Runtime::kDefineGetterPropertyUnchecked, 4); | 1597 __ CallRuntime(Runtime::kDefineGetterPropertyUnchecked); |
1598 break; | 1598 break; |
1599 | 1599 |
1600 case ObjectLiteral::Property::SETTER: | 1600 case ObjectLiteral::Property::SETTER: |
1601 __ Push(Smi::FromInt(NONE)); | 1601 __ Push(Smi::FromInt(NONE)); |
1602 __ CallRuntime(Runtime::kDefineSetterPropertyUnchecked, 4); | 1602 __ CallRuntime(Runtime::kDefineSetterPropertyUnchecked); |
1603 break; | 1603 break; |
1604 } | 1604 } |
1605 } | 1605 } |
1606 } | 1606 } |
1607 | 1607 |
1608 if (expr->has_function()) { | 1608 if (expr->has_function()) { |
1609 DCHECK(result_saved); | 1609 DCHECK(result_saved); |
1610 __ Push(Operand(rsp, 0)); | 1610 __ Push(Operand(rsp, 0)); |
1611 __ CallRuntime(Runtime::kToFastProperties, 1); | 1611 __ CallRuntime(Runtime::kToFastProperties); |
1612 } | 1612 } |
1613 | 1613 |
1614 if (result_saved) { | 1614 if (result_saved) { |
1615 context()->PlugTOS(); | 1615 context()->PlugTOS(); |
1616 } else { | 1616 } else { |
1617 context()->Plug(rax); | 1617 context()->Plug(rax); |
1618 } | 1618 } |
1619 } | 1619 } |
1620 | 1620 |
1621 | 1621 |
1622 void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { | 1622 void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { |
1623 Comment cmnt(masm_, "[ ArrayLiteral"); | 1623 Comment cmnt(masm_, "[ ArrayLiteral"); |
1624 | 1624 |
1625 Handle<FixedArray> constant_elements = expr->constant_elements(); | 1625 Handle<FixedArray> constant_elements = expr->constant_elements(); |
1626 bool has_constant_fast_elements = | 1626 bool has_constant_fast_elements = |
1627 IsFastObjectElementsKind(expr->constant_elements_kind()); | 1627 IsFastObjectElementsKind(expr->constant_elements_kind()); |
1628 | 1628 |
1629 AllocationSiteMode allocation_site_mode = TRACK_ALLOCATION_SITE; | 1629 AllocationSiteMode allocation_site_mode = TRACK_ALLOCATION_SITE; |
1630 if (has_constant_fast_elements && !FLAG_allocation_site_pretenuring) { | 1630 if (has_constant_fast_elements && !FLAG_allocation_site_pretenuring) { |
1631 // If the only customer of allocation sites is transitioning, then | 1631 // If the only customer of allocation sites is transitioning, then |
1632 // we can turn it off if we don't have anywhere else to transition to. | 1632 // we can turn it off if we don't have anywhere else to transition to. |
1633 allocation_site_mode = DONT_TRACK_ALLOCATION_SITE; | 1633 allocation_site_mode = DONT_TRACK_ALLOCATION_SITE; |
1634 } | 1634 } |
1635 | 1635 |
1636 if (MustCreateArrayLiteralWithRuntime(expr)) { | 1636 if (MustCreateArrayLiteralWithRuntime(expr)) { |
1637 __ Push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); | 1637 __ Push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); |
1638 __ Push(Smi::FromInt(expr->literal_index())); | 1638 __ Push(Smi::FromInt(expr->literal_index())); |
1639 __ Push(constant_elements); | 1639 __ Push(constant_elements); |
1640 __ Push(Smi::FromInt(expr->ComputeFlags())); | 1640 __ Push(Smi::FromInt(expr->ComputeFlags())); |
1641 __ CallRuntime(Runtime::kCreateArrayLiteral, 4); | 1641 __ CallRuntime(Runtime::kCreateArrayLiteral); |
1642 } else { | 1642 } else { |
1643 __ movp(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); | 1643 __ movp(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); |
1644 __ Move(rbx, Smi::FromInt(expr->literal_index())); | 1644 __ Move(rbx, Smi::FromInt(expr->literal_index())); |
1645 __ Move(rcx, constant_elements); | 1645 __ Move(rcx, constant_elements); |
1646 FastCloneShallowArrayStub stub(isolate(), allocation_site_mode); | 1646 FastCloneShallowArrayStub stub(isolate(), allocation_site_mode); |
1647 __ CallStub(&stub); | 1647 __ CallStub(&stub); |
1648 } | 1648 } |
1649 PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG); | 1649 PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG); |
1650 | 1650 |
1651 bool result_saved = false; // Is the result saved to the stack? | 1651 bool result_saved = false; // Is the result saved to the stack? |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1691 for (; array_index < length; array_index++) { | 1691 for (; array_index < length; array_index++) { |
1692 Expression* subexpr = subexprs->at(array_index); | 1692 Expression* subexpr = subexprs->at(array_index); |
1693 | 1693 |
1694 __ Push(rax); | 1694 __ Push(rax); |
1695 if (subexpr->IsSpread()) { | 1695 if (subexpr->IsSpread()) { |
1696 VisitForStackValue(subexpr->AsSpread()->expression()); | 1696 VisitForStackValue(subexpr->AsSpread()->expression()); |
1697 __ InvokeBuiltin(Context::CONCAT_ITERABLE_TO_ARRAY_BUILTIN_INDEX, | 1697 __ InvokeBuiltin(Context::CONCAT_ITERABLE_TO_ARRAY_BUILTIN_INDEX, |
1698 CALL_FUNCTION); | 1698 CALL_FUNCTION); |
1699 } else { | 1699 } else { |
1700 VisitForStackValue(subexpr); | 1700 VisitForStackValue(subexpr); |
1701 __ CallRuntime(Runtime::kAppendElement, 2); | 1701 __ CallRuntime(Runtime::kAppendElement); |
1702 } | 1702 } |
1703 | 1703 |
1704 PrepareForBailoutForId(expr->GetIdForElement(array_index), NO_REGISTERS); | 1704 PrepareForBailoutForId(expr->GetIdForElement(array_index), NO_REGISTERS); |
1705 } | 1705 } |
1706 | 1706 |
1707 if (result_saved) { | 1707 if (result_saved) { |
1708 context()->PlugTOS(); | 1708 context()->PlugTOS(); |
1709 } else { | 1709 } else { |
1710 context()->Plug(rax); | 1710 context()->Plug(rax); |
1711 } | 1711 } |
(...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2088 Label push_operand_holes, call_resume; | 2088 Label push_operand_holes, call_resume; |
2089 __ bind(&push_operand_holes); | 2089 __ bind(&push_operand_holes); |
2090 __ subp(rdx, Immediate(1)); | 2090 __ subp(rdx, Immediate(1)); |
2091 __ j(carry, &call_resume); | 2091 __ j(carry, &call_resume); |
2092 __ Push(rcx); | 2092 __ Push(rcx); |
2093 __ jmp(&push_operand_holes); | 2093 __ jmp(&push_operand_holes); |
2094 __ bind(&call_resume); | 2094 __ bind(&call_resume); |
2095 __ Push(rbx); | 2095 __ Push(rbx); |
2096 __ Push(result_register()); | 2096 __ Push(result_register()); |
2097 __ Push(Smi::FromInt(resume_mode)); | 2097 __ Push(Smi::FromInt(resume_mode)); |
2098 __ CallRuntime(Runtime::kResumeJSGeneratorObject, 3); | 2098 __ CallRuntime(Runtime::kResumeJSGeneratorObject); |
2099 // Not reached: the runtime call returns elsewhere. | 2099 // Not reached: the runtime call returns elsewhere. |
2100 __ Abort(kGeneratorFailedToResume); | 2100 __ Abort(kGeneratorFailedToResume); |
2101 | 2101 |
2102 __ bind(&done); | 2102 __ bind(&done); |
2103 context()->Plug(result_register()); | 2103 context()->Plug(result_register()); |
2104 } | 2104 } |
2105 | 2105 |
2106 | 2106 |
2107 void FullCodeGenerator::EmitCreateIteratorResult(bool done) { | 2107 void FullCodeGenerator::EmitCreateIteratorResult(bool done) { |
2108 Label allocate, done_allocate; | 2108 Label allocate, done_allocate; |
2109 | 2109 |
2110 __ Allocate(JSIteratorResult::kSize, rax, rcx, rdx, &allocate, TAG_OBJECT); | 2110 __ Allocate(JSIteratorResult::kSize, rax, rcx, rdx, &allocate, TAG_OBJECT); |
2111 __ jmp(&done_allocate, Label::kNear); | 2111 __ jmp(&done_allocate, Label::kNear); |
2112 | 2112 |
2113 __ bind(&allocate); | 2113 __ bind(&allocate); |
2114 __ Push(Smi::FromInt(JSIteratorResult::kSize)); | 2114 __ Push(Smi::FromInt(JSIteratorResult::kSize)); |
2115 __ CallRuntime(Runtime::kAllocateInNewSpace, 1); | 2115 __ CallRuntime(Runtime::kAllocateInNewSpace); |
2116 | 2116 |
2117 __ bind(&done_allocate); | 2117 __ bind(&done_allocate); |
2118 __ LoadNativeContextSlot(Context::ITERATOR_RESULT_MAP_INDEX, rbx); | 2118 __ LoadNativeContextSlot(Context::ITERATOR_RESULT_MAP_INDEX, rbx); |
2119 __ movp(FieldOperand(rax, HeapObject::kMapOffset), rbx); | 2119 __ movp(FieldOperand(rax, HeapObject::kMapOffset), rbx); |
2120 __ LoadRoot(rbx, Heap::kEmptyFixedArrayRootIndex); | 2120 __ LoadRoot(rbx, Heap::kEmptyFixedArrayRootIndex); |
2121 __ movp(FieldOperand(rax, JSObject::kPropertiesOffset), rbx); | 2121 __ movp(FieldOperand(rax, JSObject::kPropertiesOffset), rbx); |
2122 __ movp(FieldOperand(rax, JSObject::kElementsOffset), rbx); | 2122 __ movp(FieldOperand(rax, JSObject::kElementsOffset), rbx); |
2123 __ Pop(FieldOperand(rax, JSIteratorResult::kValueOffset)); | 2123 __ Pop(FieldOperand(rax, JSIteratorResult::kValueOffset)); |
2124 __ LoadRoot(FieldOperand(rax, JSIteratorResult::kDoneOffset), | 2124 __ LoadRoot(FieldOperand(rax, JSIteratorResult::kDoneOffset), |
2125 done ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex); | 2125 done ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex); |
(...skipping 15 matching lines...) Expand all Loading... |
2141 | 2141 |
2142 void FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) { | 2142 void FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) { |
2143 // Stack: receiver, home_object | 2143 // Stack: receiver, home_object |
2144 SetExpressionPosition(prop); | 2144 SetExpressionPosition(prop); |
2145 Literal* key = prop->key()->AsLiteral(); | 2145 Literal* key = prop->key()->AsLiteral(); |
2146 DCHECK(!key->value()->IsSmi()); | 2146 DCHECK(!key->value()->IsSmi()); |
2147 DCHECK(prop->IsSuperAccess()); | 2147 DCHECK(prop->IsSuperAccess()); |
2148 | 2148 |
2149 __ Push(key->value()); | 2149 __ Push(key->value()); |
2150 __ Push(Smi::FromInt(language_mode())); | 2150 __ Push(Smi::FromInt(language_mode())); |
2151 __ CallRuntime(Runtime::kLoadFromSuper, 4); | 2151 __ CallRuntime(Runtime::kLoadFromSuper); |
2152 } | 2152 } |
2153 | 2153 |
2154 | 2154 |
2155 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { | 2155 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { |
2156 SetExpressionPosition(prop); | 2156 SetExpressionPosition(prop); |
2157 Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate(), language_mode()).code(); | 2157 Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate(), language_mode()).code(); |
2158 __ Move(LoadDescriptor::SlotRegister(), | 2158 __ Move(LoadDescriptor::SlotRegister(), |
2159 SmiFromSlot(prop->PropertyFeedbackSlot())); | 2159 SmiFromSlot(prop->PropertyFeedbackSlot())); |
2160 CallIC(ic); | 2160 CallIC(ic); |
2161 } | 2161 } |
2162 | 2162 |
2163 | 2163 |
2164 void FullCodeGenerator::EmitKeyedSuperPropertyLoad(Property* prop) { | 2164 void FullCodeGenerator::EmitKeyedSuperPropertyLoad(Property* prop) { |
2165 // Stack: receiver, home_object, key. | 2165 // Stack: receiver, home_object, key. |
2166 SetExpressionPosition(prop); | 2166 SetExpressionPosition(prop); |
2167 __ Push(Smi::FromInt(language_mode())); | 2167 __ Push(Smi::FromInt(language_mode())); |
2168 __ CallRuntime(Runtime::kLoadKeyedFromSuper, 4); | 2168 __ CallRuntime(Runtime::kLoadKeyedFromSuper); |
2169 } | 2169 } |
2170 | 2170 |
2171 | 2171 |
2172 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, | 2172 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, |
2173 Token::Value op, | 2173 Token::Value op, |
2174 Expression* left, | 2174 Expression* left, |
2175 Expression* right) { | 2175 Expression* right) { |
2176 // Do combined smi check of the operands. Left operand is on the | 2176 // Do combined smi check of the operands. Left operand is on the |
2177 // stack (popped into rdx). Right operand is in rax but moved into | 2177 // stack (popped into rdx). Right operand is in rax but moved into |
2178 // rcx to make the shifts easier. | 2178 // rcx to make the shifts easier. |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2250 } else { | 2250 } else { |
2251 __ Push(Operand(rsp, 0)); // prototype | 2251 __ Push(Operand(rsp, 0)); // prototype |
2252 } | 2252 } |
2253 EmitPropertyKey(property, lit->GetIdForProperty(i)); | 2253 EmitPropertyKey(property, lit->GetIdForProperty(i)); |
2254 | 2254 |
2255 // The static prototype property is read only. We handle the non computed | 2255 // The static prototype property is read only. We handle the non computed |
2256 // property name case in the parser. Since this is the only case where we | 2256 // property name case in the parser. Since this is the only case where we |
2257 // need to check for an own read only property we special case this so we do | 2257 // need to check for an own read only property we special case this so we do |
2258 // not need to do this for every property. | 2258 // not need to do this for every property. |
2259 if (property->is_static() && property->is_computed_name()) { | 2259 if (property->is_static() && property->is_computed_name()) { |
2260 __ CallRuntime(Runtime::kThrowIfStaticPrototype, 1); | 2260 __ CallRuntime(Runtime::kThrowIfStaticPrototype); |
2261 __ Push(rax); | 2261 __ Push(rax); |
2262 } | 2262 } |
2263 | 2263 |
2264 VisitForStackValue(value); | 2264 VisitForStackValue(value); |
2265 if (NeedsHomeObject(value)) { | 2265 if (NeedsHomeObject(value)) { |
2266 EmitSetHomeObject(value, 2, property->GetSlot()); | 2266 EmitSetHomeObject(value, 2, property->GetSlot()); |
2267 } | 2267 } |
2268 | 2268 |
2269 switch (property->kind()) { | 2269 switch (property->kind()) { |
2270 case ObjectLiteral::Property::CONSTANT: | 2270 case ObjectLiteral::Property::CONSTANT: |
2271 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 2271 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
2272 case ObjectLiteral::Property::PROTOTYPE: | 2272 case ObjectLiteral::Property::PROTOTYPE: |
2273 UNREACHABLE(); | 2273 UNREACHABLE(); |
2274 case ObjectLiteral::Property::COMPUTED: | 2274 case ObjectLiteral::Property::COMPUTED: |
2275 __ CallRuntime(Runtime::kDefineClassMethod, 3); | 2275 __ CallRuntime(Runtime::kDefineClassMethod); |
2276 break; | 2276 break; |
2277 | 2277 |
2278 case ObjectLiteral::Property::GETTER: | 2278 case ObjectLiteral::Property::GETTER: |
2279 __ Push(Smi::FromInt(DONT_ENUM)); | 2279 __ Push(Smi::FromInt(DONT_ENUM)); |
2280 __ CallRuntime(Runtime::kDefineGetterPropertyUnchecked, 4); | 2280 __ CallRuntime(Runtime::kDefineGetterPropertyUnchecked); |
2281 break; | 2281 break; |
2282 | 2282 |
2283 case ObjectLiteral::Property::SETTER: | 2283 case ObjectLiteral::Property::SETTER: |
2284 __ Push(Smi::FromInt(DONT_ENUM)); | 2284 __ Push(Smi::FromInt(DONT_ENUM)); |
2285 __ CallRuntime(Runtime::kDefineSetterPropertyUnchecked, 4); | 2285 __ CallRuntime(Runtime::kDefineSetterPropertyUnchecked); |
2286 break; | 2286 break; |
2287 | 2287 |
2288 default: | 2288 default: |
2289 UNREACHABLE(); | 2289 UNREACHABLE(); |
2290 } | 2290 } |
2291 } | 2291 } |
2292 | 2292 |
2293 // Set both the prototype and constructor to have fast properties, and also | 2293 // Set both the prototype and constructor to have fast properties, and also |
2294 // freeze them in strong mode. | 2294 // freeze them in strong mode. |
2295 __ CallRuntime(Runtime::kFinalizeClassDefinition, 2); | 2295 __ CallRuntime(Runtime::kFinalizeClassDefinition); |
2296 } | 2296 } |
2297 | 2297 |
2298 | 2298 |
2299 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, Token::Value op) { | 2299 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, Token::Value op) { |
2300 __ Pop(rdx); | 2300 __ Pop(rdx); |
2301 Handle<Code> code = | 2301 Handle<Code> code = |
2302 CodeFactory::BinaryOpIC(isolate(), op, strength(language_mode())).code(); | 2302 CodeFactory::BinaryOpIC(isolate(), op, strength(language_mode())).code(); |
2303 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. | 2303 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. |
2304 CallIC(code, expr->BinaryOperationFeedbackId()); | 2304 CallIC(code, expr->BinaryOperationFeedbackId()); |
2305 patch_site.EmitPatchInfo(); | 2305 patch_site.EmitPatchInfo(); |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2410 } else if (var->mode() == LET && op != Token::INIT) { | 2410 } else if (var->mode() == LET && op != Token::INIT) { |
2411 // Non-initializing assignment to let variable needs a write barrier. | 2411 // Non-initializing assignment to let variable needs a write barrier. |
2412 DCHECK(!var->IsLookupSlot()); | 2412 DCHECK(!var->IsLookupSlot()); |
2413 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); | 2413 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
2414 Label assign; | 2414 Label assign; |
2415 MemOperand location = VarOperand(var, rcx); | 2415 MemOperand location = VarOperand(var, rcx); |
2416 __ movp(rdx, location); | 2416 __ movp(rdx, location); |
2417 __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex); | 2417 __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex); |
2418 __ j(not_equal, &assign, Label::kNear); | 2418 __ j(not_equal, &assign, Label::kNear); |
2419 __ Push(var->name()); | 2419 __ Push(var->name()); |
2420 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 2420 __ CallRuntime(Runtime::kThrowReferenceError); |
2421 __ bind(&assign); | 2421 __ bind(&assign); |
2422 EmitStoreToStackLocalOrContextSlot(var, location); | 2422 EmitStoreToStackLocalOrContextSlot(var, location); |
2423 | 2423 |
2424 } else if (var->mode() == CONST && op != Token::INIT) { | 2424 } else if (var->mode() == CONST && op != Token::INIT) { |
2425 // Assignment to const variable needs a write barrier. | 2425 // Assignment to const variable needs a write barrier. |
2426 DCHECK(!var->IsLookupSlot()); | 2426 DCHECK(!var->IsLookupSlot()); |
2427 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); | 2427 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
2428 Label const_error; | 2428 Label const_error; |
2429 MemOperand location = VarOperand(var, rcx); | 2429 MemOperand location = VarOperand(var, rcx); |
2430 __ movp(rdx, location); | 2430 __ movp(rdx, location); |
2431 __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex); | 2431 __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex); |
2432 __ j(not_equal, &const_error, Label::kNear); | 2432 __ j(not_equal, &const_error, Label::kNear); |
2433 __ Push(var->name()); | 2433 __ Push(var->name()); |
2434 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 2434 __ CallRuntime(Runtime::kThrowReferenceError); |
2435 __ bind(&const_error); | 2435 __ bind(&const_error); |
2436 __ CallRuntime(Runtime::kThrowConstAssignError, 0); | 2436 __ CallRuntime(Runtime::kThrowConstAssignError); |
2437 | 2437 |
2438 } else if (var->is_this() && var->mode() == CONST && op == Token::INIT) { | 2438 } else if (var->is_this() && var->mode() == CONST && op == Token::INIT) { |
2439 // Initializing assignment to const {this} needs a write barrier. | 2439 // Initializing assignment to const {this} needs a write barrier. |
2440 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); | 2440 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
2441 Label uninitialized_this; | 2441 Label uninitialized_this; |
2442 MemOperand location = VarOperand(var, rcx); | 2442 MemOperand location = VarOperand(var, rcx); |
2443 __ movp(rdx, location); | 2443 __ movp(rdx, location); |
2444 __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex); | 2444 __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex); |
2445 __ j(equal, &uninitialized_this); | 2445 __ j(equal, &uninitialized_this); |
2446 __ Push(var->name()); | 2446 __ Push(var->name()); |
2447 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 2447 __ CallRuntime(Runtime::kThrowReferenceError); |
2448 __ bind(&uninitialized_this); | 2448 __ bind(&uninitialized_this); |
2449 EmitStoreToStackLocalOrContextSlot(var, location); | 2449 EmitStoreToStackLocalOrContextSlot(var, location); |
2450 | 2450 |
2451 } else if (!var->is_const_mode() || | 2451 } else if (!var->is_const_mode() || |
2452 (var->mode() == CONST && op == Token::INIT)) { | 2452 (var->mode() == CONST && op == Token::INIT)) { |
2453 if (var->IsLookupSlot()) { | 2453 if (var->IsLookupSlot()) { |
2454 // Assignment to var. | 2454 // Assignment to var. |
2455 __ Push(rax); // Value. | 2455 __ Push(rax); // Value. |
2456 __ Push(rsi); // Context. | 2456 __ Push(rsi); // Context. |
2457 __ Push(var->name()); | 2457 __ Push(var->name()); |
2458 __ Push(Smi::FromInt(language_mode())); | 2458 __ Push(Smi::FromInt(language_mode())); |
2459 __ CallRuntime(Runtime::kStoreLookupSlot, 4); | 2459 __ CallRuntime(Runtime::kStoreLookupSlot); |
2460 } else { | 2460 } else { |
2461 // Assignment to var or initializing assignment to let/const in harmony | 2461 // Assignment to var or initializing assignment to let/const in harmony |
2462 // mode. | 2462 // mode. |
2463 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); | 2463 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
2464 MemOperand location = VarOperand(var, rcx); | 2464 MemOperand location = VarOperand(var, rcx); |
2465 if (generate_debug_code_ && var->mode() == LET && op == Token::INIT) { | 2465 if (generate_debug_code_ && var->mode() == LET && op == Token::INIT) { |
2466 // Check for an uninitialized let binding. | 2466 // Check for an uninitialized let binding. |
2467 __ movp(rdx, location); | 2467 __ movp(rdx, location); |
2468 __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex); | 2468 __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex); |
2469 __ Check(equal, kLetBindingReInitialization); | 2469 __ Check(equal, kLetBindingReInitialization); |
2470 } | 2470 } |
2471 EmitStoreToStackLocalOrContextSlot(var, location); | 2471 EmitStoreToStackLocalOrContextSlot(var, location); |
2472 } | 2472 } |
2473 | 2473 |
2474 } else if (var->mode() == CONST_LEGACY && op == Token::INIT) { | 2474 } else if (var->mode() == CONST_LEGACY && op == Token::INIT) { |
2475 // Const initializers need a write barrier. | 2475 // Const initializers need a write barrier. |
2476 DCHECK(!var->IsParameter()); // No const parameters. | 2476 DCHECK(!var->IsParameter()); // No const parameters. |
2477 if (var->IsLookupSlot()) { | 2477 if (var->IsLookupSlot()) { |
2478 __ Push(rax); | 2478 __ Push(rax); |
2479 __ Push(rsi); | 2479 __ Push(rsi); |
2480 __ Push(var->name()); | 2480 __ Push(var->name()); |
2481 __ CallRuntime(Runtime::kInitializeLegacyConstLookupSlot, 3); | 2481 __ CallRuntime(Runtime::kInitializeLegacyConstLookupSlot); |
2482 } else { | 2482 } else { |
2483 DCHECK(var->IsStackLocal() || var->IsContextSlot()); | 2483 DCHECK(var->IsStackLocal() || var->IsContextSlot()); |
2484 Label skip; | 2484 Label skip; |
2485 MemOperand location = VarOperand(var, rcx); | 2485 MemOperand location = VarOperand(var, rcx); |
2486 __ movp(rdx, location); | 2486 __ movp(rdx, location); |
2487 __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex); | 2487 __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex); |
2488 __ j(not_equal, &skip); | 2488 __ j(not_equal, &skip); |
2489 EmitStoreToStackLocalOrContextSlot(var, location); | 2489 EmitStoreToStackLocalOrContextSlot(var, location); |
2490 __ bind(&skip); | 2490 __ bind(&skip); |
2491 } | 2491 } |
2492 | 2492 |
2493 } else { | 2493 } else { |
2494 DCHECK(var->mode() == CONST_LEGACY && op != Token::INIT); | 2494 DCHECK(var->mode() == CONST_LEGACY && op != Token::INIT); |
2495 if (is_strict(language_mode())) { | 2495 if (is_strict(language_mode())) { |
2496 __ CallRuntime(Runtime::kThrowConstAssignError, 0); | 2496 __ CallRuntime(Runtime::kThrowConstAssignError); |
2497 } | 2497 } |
2498 // Silently ignore store in sloppy mode. | 2498 // Silently ignore store in sloppy mode. |
2499 } | 2499 } |
2500 } | 2500 } |
2501 | 2501 |
2502 | 2502 |
2503 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { | 2503 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { |
2504 // Assignment to a property, using a named store IC. | 2504 // Assignment to a property, using a named store IC. |
2505 Property* prop = expr->target()->AsProperty(); | 2505 Property* prop = expr->target()->AsProperty(); |
2506 DCHECK(prop != NULL); | 2506 DCHECK(prop != NULL); |
(...skipping 13 matching lines...) Expand all Loading... |
2520 // Assignment to named property of super. | 2520 // Assignment to named property of super. |
2521 // rax : value | 2521 // rax : value |
2522 // stack : receiver ('this'), home_object | 2522 // stack : receiver ('this'), home_object |
2523 DCHECK(prop != NULL); | 2523 DCHECK(prop != NULL); |
2524 Literal* key = prop->key()->AsLiteral(); | 2524 Literal* key = prop->key()->AsLiteral(); |
2525 DCHECK(key != NULL); | 2525 DCHECK(key != NULL); |
2526 | 2526 |
2527 __ Push(key->value()); | 2527 __ Push(key->value()); |
2528 __ Push(rax); | 2528 __ Push(rax); |
2529 __ CallRuntime((is_strict(language_mode()) ? Runtime::kStoreToSuper_Strict | 2529 __ CallRuntime((is_strict(language_mode()) ? Runtime::kStoreToSuper_Strict |
2530 : Runtime::kStoreToSuper_Sloppy), | 2530 : Runtime::kStoreToSuper_Sloppy)); |
2531 4); | |
2532 } | 2531 } |
2533 | 2532 |
2534 | 2533 |
2535 void FullCodeGenerator::EmitKeyedSuperPropertyStore(Property* prop) { | 2534 void FullCodeGenerator::EmitKeyedSuperPropertyStore(Property* prop) { |
2536 // Assignment to named property of super. | 2535 // Assignment to named property of super. |
2537 // rax : value | 2536 // rax : value |
2538 // stack : receiver ('this'), home_object, key | 2537 // stack : receiver ('this'), home_object, key |
2539 DCHECK(prop != NULL); | 2538 DCHECK(prop != NULL); |
2540 | 2539 |
2541 __ Push(rax); | 2540 __ Push(rax); |
2542 __ CallRuntime( | 2541 __ CallRuntime((is_strict(language_mode()) |
2543 (is_strict(language_mode()) ? Runtime::kStoreKeyedToSuper_Strict | 2542 ? Runtime::kStoreKeyedToSuper_Strict |
2544 : Runtime::kStoreKeyedToSuper_Sloppy), | 2543 : Runtime::kStoreKeyedToSuper_Sloppy)); |
2545 4); | |
2546 } | 2544 } |
2547 | 2545 |
2548 | 2546 |
2549 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { | 2547 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { |
2550 // Assignment to a property, using a keyed store IC. | 2548 // Assignment to a property, using a keyed store IC. |
2551 __ Pop(StoreDescriptor::NameRegister()); // Key. | 2549 __ Pop(StoreDescriptor::NameRegister()); // Key. |
2552 __ Pop(StoreDescriptor::ReceiverRegister()); | 2550 __ Pop(StoreDescriptor::ReceiverRegister()); |
2553 DCHECK(StoreDescriptor::ValueRegister().is(rax)); | 2551 DCHECK(StoreDescriptor::ValueRegister().is(rax)); |
2554 Handle<Code> ic = | 2552 Handle<Code> ic = |
2555 CodeFactory::KeyedStoreIC(isolate(), language_mode()).code(); | 2553 CodeFactory::KeyedStoreIC(isolate(), language_mode()).code(); |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2657 __ Push(key->value()); | 2655 __ Push(key->value()); |
2658 __ Push(Smi::FromInt(language_mode())); | 2656 __ Push(Smi::FromInt(language_mode())); |
2659 | 2657 |
2660 // Stack here: | 2658 // Stack here: |
2661 // - home_object | 2659 // - home_object |
2662 // - this (receiver) | 2660 // - this (receiver) |
2663 // - this (receiver) <-- LoadFromSuper will pop here and below. | 2661 // - this (receiver) <-- LoadFromSuper will pop here and below. |
2664 // - home_object | 2662 // - home_object |
2665 // - key | 2663 // - key |
2666 // - language_mode | 2664 // - language_mode |
2667 __ CallRuntime(Runtime::kLoadFromSuper, 4); | 2665 __ CallRuntime(Runtime::kLoadFromSuper); |
2668 | 2666 |
2669 // Replace home_object with target function. | 2667 // Replace home_object with target function. |
2670 __ movp(Operand(rsp, kPointerSize), rax); | 2668 __ movp(Operand(rsp, kPointerSize), rax); |
2671 | 2669 |
2672 // Stack here: | 2670 // Stack here: |
2673 // - target function | 2671 // - target function |
2674 // - this (receiver) | 2672 // - this (receiver) |
2675 EmitCall(expr); | 2673 EmitCall(expr); |
2676 } | 2674 } |
2677 | 2675 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2716 VisitForStackValue(prop->key()); | 2714 VisitForStackValue(prop->key()); |
2717 __ Push(Smi::FromInt(language_mode())); | 2715 __ Push(Smi::FromInt(language_mode())); |
2718 | 2716 |
2719 // Stack here: | 2717 // Stack here: |
2720 // - home_object | 2718 // - home_object |
2721 // - this (receiver) | 2719 // - this (receiver) |
2722 // - this (receiver) <-- LoadKeyedFromSuper will pop here and below. | 2720 // - this (receiver) <-- LoadKeyedFromSuper will pop here and below. |
2723 // - home_object | 2721 // - home_object |
2724 // - key | 2722 // - key |
2725 // - language_mode | 2723 // - language_mode |
2726 __ CallRuntime(Runtime::kLoadKeyedFromSuper, 4); | 2724 __ CallRuntime(Runtime::kLoadKeyedFromSuper); |
2727 | 2725 |
2728 // Replace home_object with target function. | 2726 // Replace home_object with target function. |
2729 __ movp(Operand(rsp, kPointerSize), rax); | 2727 __ movp(Operand(rsp, kPointerSize), rax); |
2730 | 2728 |
2731 // Stack here: | 2729 // Stack here: |
2732 // - target function | 2730 // - target function |
2733 // - this (receiver) | 2731 // - this (receiver) |
2734 EmitCall(expr); | 2732 EmitCall(expr); |
2735 } | 2733 } |
2736 | 2734 |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2772 // Push the enclosing function. | 2770 // Push the enclosing function. |
2773 __ Push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); | 2771 __ Push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); |
2774 | 2772 |
2775 // Push the language mode. | 2773 // Push the language mode. |
2776 __ Push(Smi::FromInt(language_mode())); | 2774 __ Push(Smi::FromInt(language_mode())); |
2777 | 2775 |
2778 // Push the start position of the scope the calls resides in. | 2776 // Push the start position of the scope the calls resides in. |
2779 __ Push(Smi::FromInt(scope()->start_position())); | 2777 __ Push(Smi::FromInt(scope()->start_position())); |
2780 | 2778 |
2781 // Do the runtime call. | 2779 // Do the runtime call. |
2782 __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5); | 2780 __ CallRuntime(Runtime::kResolvePossiblyDirectEval); |
2783 } | 2781 } |
2784 | 2782 |
2785 | 2783 |
2786 // See http://www.ecma-international.org/ecma-262/6.0/#sec-function-calls. | 2784 // See http://www.ecma-international.org/ecma-262/6.0/#sec-function-calls. |
2787 void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) { | 2785 void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) { |
2788 VariableProxy* callee = expr->expression()->AsVariableProxy(); | 2786 VariableProxy* callee = expr->expression()->AsVariableProxy(); |
2789 if (callee->var()->IsLookupSlot()) { | 2787 if (callee->var()->IsLookupSlot()) { |
2790 Label slow, done; | 2788 Label slow, done; |
2791 SetExpressionPosition(callee); | 2789 SetExpressionPosition(callee); |
2792 // Generate code for loading from variables potentially shadowed by | 2790 // Generate code for loading from variables potentially shadowed by |
2793 // eval-introduced variables. | 2791 // eval-introduced variables. |
2794 EmitDynamicLookupFastCase(callee, NOT_INSIDE_TYPEOF, &slow, &done); | 2792 EmitDynamicLookupFastCase(callee, NOT_INSIDE_TYPEOF, &slow, &done); |
2795 __ bind(&slow); | 2793 __ bind(&slow); |
2796 // Call the runtime to find the function to call (returned in rax) and | 2794 // Call the runtime to find the function to call (returned in rax) and |
2797 // the object holding it (returned in rdx). | 2795 // the object holding it (returned in rdx). |
2798 __ Push(context_register()); | 2796 __ Push(context_register()); |
2799 __ Push(callee->name()); | 2797 __ Push(callee->name()); |
2800 __ CallRuntime(Runtime::kLoadLookupSlot, 2); | 2798 __ CallRuntime(Runtime::kLoadLookupSlot); |
2801 __ Push(rax); // Function. | 2799 __ Push(rax); // Function. |
2802 __ Push(rdx); // Receiver. | 2800 __ Push(rdx); // Receiver. |
2803 PrepareForBailoutForId(expr->LookupId(), NO_REGISTERS); | 2801 PrepareForBailoutForId(expr->LookupId(), NO_REGISTERS); |
2804 | 2802 |
2805 // If fast case code has been generated, emit code to push the function | 2803 // If fast case code has been generated, emit code to push the function |
2806 // and receiver and have the slow path jump around this code. | 2804 // and receiver and have the slow path jump around this code. |
2807 if (done.is_linked()) { | 2805 if (done.is_linked()) { |
2808 Label call; | 2806 Label call; |
2809 __ jmp(&call, Label::kNear); | 2807 __ jmp(&call, Label::kNear); |
2810 __ bind(&done); | 2808 __ bind(&done); |
(...skipping 628 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3439 ZoneList<Expression*>* args = expr->arguments(); | 3437 ZoneList<Expression*>* args = expr->arguments(); |
3440 DCHECK_EQ(1, args->length()); | 3438 DCHECK_EQ(1, args->length()); |
3441 | 3439 |
3442 // Load the argument into rax and convert it. | 3440 // Load the argument into rax and convert it. |
3443 VisitForAccumulatorValue(args->at(0)); | 3441 VisitForAccumulatorValue(args->at(0)); |
3444 | 3442 |
3445 // Convert the object to an integer. | 3443 // Convert the object to an integer. |
3446 Label done_convert; | 3444 Label done_convert; |
3447 __ JumpIfSmi(rax, &done_convert, Label::kNear); | 3445 __ JumpIfSmi(rax, &done_convert, Label::kNear); |
3448 __ Push(rax); | 3446 __ Push(rax); |
3449 __ CallRuntime(Runtime::kToInteger, 1); | 3447 __ CallRuntime(Runtime::kToInteger); |
3450 __ bind(&done_convert); | 3448 __ bind(&done_convert); |
3451 context()->Plug(rax); | 3449 context()->Plug(rax); |
3452 } | 3450 } |
3453 | 3451 |
3454 | 3452 |
3455 void FullCodeGenerator::EmitToName(CallRuntime* expr) { | 3453 void FullCodeGenerator::EmitToName(CallRuntime* expr) { |
3456 ZoneList<Expression*>* args = expr->arguments(); | 3454 ZoneList<Expression*>* args = expr->arguments(); |
3457 DCHECK_EQ(1, args->length()); | 3455 DCHECK_EQ(1, args->length()); |
3458 | 3456 |
3459 // Load the argument into rax and convert it. | 3457 // Load the argument into rax and convert it. |
3460 VisitForAccumulatorValue(args->at(0)); | 3458 VisitForAccumulatorValue(args->at(0)); |
3461 | 3459 |
3462 // Convert the object to a name. | 3460 // Convert the object to a name. |
3463 Label convert, done_convert; | 3461 Label convert, done_convert; |
3464 __ JumpIfSmi(rax, &convert, Label::kNear); | 3462 __ JumpIfSmi(rax, &convert, Label::kNear); |
3465 STATIC_ASSERT(FIRST_NAME_TYPE == FIRST_TYPE); | 3463 STATIC_ASSERT(FIRST_NAME_TYPE == FIRST_TYPE); |
3466 __ CmpObjectType(rax, LAST_NAME_TYPE, rcx); | 3464 __ CmpObjectType(rax, LAST_NAME_TYPE, rcx); |
3467 __ j(below_equal, &done_convert, Label::kNear); | 3465 __ j(below_equal, &done_convert, Label::kNear); |
3468 __ bind(&convert); | 3466 __ bind(&convert); |
3469 __ Push(rax); | 3467 __ Push(rax); |
3470 __ CallRuntime(Runtime::kToName, 1); | 3468 __ CallRuntime(Runtime::kToName); |
3471 __ bind(&done_convert); | 3469 __ bind(&done_convert); |
3472 context()->Plug(rax); | 3470 context()->Plug(rax); |
3473 } | 3471 } |
3474 | 3472 |
3475 | 3473 |
3476 void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) { | 3474 void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) { |
3477 ZoneList<Expression*>* args = expr->arguments(); | 3475 ZoneList<Expression*>* args = expr->arguments(); |
3478 DCHECK(args->length() == 1); | 3476 DCHECK(args->length() == 1); |
3479 | 3477 |
3480 VisitForAccumulatorValue(args->at(0)); | 3478 VisitForAccumulatorValue(args->at(0)); |
(...skipping 489 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3970 __ movp(FieldOperand(rax, HeapObject::kMapOffset), rbx); | 3968 __ movp(FieldOperand(rax, HeapObject::kMapOffset), rbx); |
3971 __ LoadRoot(rbx, Heap::kEmptyFixedArrayRootIndex); | 3969 __ LoadRoot(rbx, Heap::kEmptyFixedArrayRootIndex); |
3972 __ movp(FieldOperand(rax, JSObject::kPropertiesOffset), rbx); | 3970 __ movp(FieldOperand(rax, JSObject::kPropertiesOffset), rbx); |
3973 __ movp(FieldOperand(rax, JSObject::kElementsOffset), rbx); | 3971 __ movp(FieldOperand(rax, JSObject::kElementsOffset), rbx); |
3974 __ Pop(FieldOperand(rax, JSIteratorResult::kDoneOffset)); | 3972 __ Pop(FieldOperand(rax, JSIteratorResult::kDoneOffset)); |
3975 __ Pop(FieldOperand(rax, JSIteratorResult::kValueOffset)); | 3973 __ Pop(FieldOperand(rax, JSIteratorResult::kValueOffset)); |
3976 STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize); | 3974 STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize); |
3977 __ jmp(&done, Label::kNear); | 3975 __ jmp(&done, Label::kNear); |
3978 | 3976 |
3979 __ bind(&runtime); | 3977 __ bind(&runtime); |
3980 __ CallRuntime(Runtime::kCreateIterResultObject, 2); | 3978 __ CallRuntime(Runtime::kCreateIterResultObject); |
3981 | 3979 |
3982 __ bind(&done); | 3980 __ bind(&done); |
3983 context()->Plug(rax); | 3981 context()->Plug(rax); |
3984 } | 3982 } |
3985 | 3983 |
3986 | 3984 |
3987 void FullCodeGenerator::EmitLoadJSRuntimeFunction(CallRuntime* expr) { | 3985 void FullCodeGenerator::EmitLoadJSRuntimeFunction(CallRuntime* expr) { |
3988 // Push the builtins object as receiver. | 3986 // Push the builtins object as receiver. |
3989 __ PushRoot(Heap::kUndefinedValueRootIndex); | 3987 __ PushRoot(Heap::kUndefinedValueRootIndex); |
3990 | 3988 |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4061 case Token::DELETE: { | 4059 case Token::DELETE: { |
4062 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); | 4060 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); |
4063 Property* property = expr->expression()->AsProperty(); | 4061 Property* property = expr->expression()->AsProperty(); |
4064 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 4062 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
4065 | 4063 |
4066 if (property != NULL) { | 4064 if (property != NULL) { |
4067 VisitForStackValue(property->obj()); | 4065 VisitForStackValue(property->obj()); |
4068 VisitForStackValue(property->key()); | 4066 VisitForStackValue(property->key()); |
4069 __ CallRuntime(is_strict(language_mode()) | 4067 __ CallRuntime(is_strict(language_mode()) |
4070 ? Runtime::kDeleteProperty_Strict | 4068 ? Runtime::kDeleteProperty_Strict |
4071 : Runtime::kDeleteProperty_Sloppy, | 4069 : Runtime::kDeleteProperty_Sloppy); |
4072 2); | |
4073 context()->Plug(rax); | 4070 context()->Plug(rax); |
4074 } else if (proxy != NULL) { | 4071 } else if (proxy != NULL) { |
4075 Variable* var = proxy->var(); | 4072 Variable* var = proxy->var(); |
4076 // Delete of an unqualified identifier is disallowed in strict mode but | 4073 // Delete of an unqualified identifier is disallowed in strict mode but |
4077 // "delete this" is allowed. | 4074 // "delete this" is allowed. |
4078 bool is_this = var->HasThisName(isolate()); | 4075 bool is_this = var->HasThisName(isolate()); |
4079 DCHECK(is_sloppy(language_mode()) || is_this); | 4076 DCHECK(is_sloppy(language_mode()) || is_this); |
4080 if (var->IsUnallocatedOrGlobalSlot()) { | 4077 if (var->IsUnallocatedOrGlobalSlot()) { |
4081 __ movp(rax, NativeContextOperand()); | 4078 __ movp(rax, NativeContextOperand()); |
4082 __ Push(ContextOperand(rax, Context::EXTENSION_INDEX)); | 4079 __ Push(ContextOperand(rax, Context::EXTENSION_INDEX)); |
4083 __ Push(var->name()); | 4080 __ Push(var->name()); |
4084 __ CallRuntime(Runtime::kDeleteProperty_Sloppy, 2); | 4081 __ CallRuntime(Runtime::kDeleteProperty_Sloppy); |
4085 context()->Plug(rax); | 4082 context()->Plug(rax); |
4086 } else if (var->IsStackAllocated() || var->IsContextSlot()) { | 4083 } else if (var->IsStackAllocated() || var->IsContextSlot()) { |
4087 // Result of deleting non-global variables is false. 'this' is | 4084 // Result of deleting non-global variables is false. 'this' is |
4088 // not really a variable, though we implement it as one. The | 4085 // not really a variable, though we implement it as one. The |
4089 // subexpression does not have side effects. | 4086 // subexpression does not have side effects. |
4090 context()->Plug(is_this); | 4087 context()->Plug(is_this); |
4091 } else { | 4088 } else { |
4092 // Non-global variable. Call the runtime to try to delete from the | 4089 // Non-global variable. Call the runtime to try to delete from the |
4093 // context where the variable was introduced. | 4090 // context where the variable was introduced. |
4094 __ Push(context_register()); | 4091 __ Push(context_register()); |
4095 __ Push(var->name()); | 4092 __ Push(var->name()); |
4096 __ CallRuntime(Runtime::kDeleteLookupSlot, 2); | 4093 __ CallRuntime(Runtime::kDeleteLookupSlot); |
4097 context()->Plug(rax); | 4094 context()->Plug(rax); |
4098 } | 4095 } |
4099 } else { | 4096 } else { |
4100 // Result of deleting non-property, non-variable reference is true. | 4097 // Result of deleting non-property, non-variable reference is true. |
4101 // The subexpression may have side effects. | 4098 // The subexpression may have side effects. |
4102 VisitForEffect(expr->expression()); | 4099 VisitForEffect(expr->expression()); |
4103 context()->Plug(true); | 4100 context()->Plug(true); |
4104 } | 4101 } |
4105 break; | 4102 break; |
4106 } | 4103 } |
(...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4521 Label* if_false = NULL; | 4518 Label* if_false = NULL; |
4522 Label* fall_through = NULL; | 4519 Label* fall_through = NULL; |
4523 context()->PrepareTest(&materialize_true, &materialize_false, | 4520 context()->PrepareTest(&materialize_true, &materialize_false, |
4524 &if_true, &if_false, &fall_through); | 4521 &if_true, &if_false, &fall_through); |
4525 | 4522 |
4526 Token::Value op = expr->op(); | 4523 Token::Value op = expr->op(); |
4527 VisitForStackValue(expr->left()); | 4524 VisitForStackValue(expr->left()); |
4528 switch (op) { | 4525 switch (op) { |
4529 case Token::IN: | 4526 case Token::IN: |
4530 VisitForStackValue(expr->right()); | 4527 VisitForStackValue(expr->right()); |
4531 __ CallRuntime(Runtime::kHasProperty, 2); | 4528 __ CallRuntime(Runtime::kHasProperty); |
4532 PrepareForBailoutBeforeSplit(expr, false, NULL, NULL); | 4529 PrepareForBailoutBeforeSplit(expr, false, NULL, NULL); |
4533 __ CompareRoot(rax, Heap::kTrueValueRootIndex); | 4530 __ CompareRoot(rax, Heap::kTrueValueRootIndex); |
4534 Split(equal, if_true, if_false, fall_through); | 4531 Split(equal, if_true, if_false, fall_through); |
4535 break; | 4532 break; |
4536 | 4533 |
4537 case Token::INSTANCEOF: { | 4534 case Token::INSTANCEOF: { |
4538 VisitForAccumulatorValue(expr->right()); | 4535 VisitForAccumulatorValue(expr->right()); |
4539 __ Pop(rdx); | 4536 __ Pop(rdx); |
4540 InstanceOfStub stub(isolate()); | 4537 InstanceOfStub stub(isolate()); |
4541 __ CallStub(&stub); | 4538 __ CallStub(&stub); |
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4795 Assembler::target_address_at(call_target_address, | 4792 Assembler::target_address_at(call_target_address, |
4796 unoptimized_code)); | 4793 unoptimized_code)); |
4797 return OSR_AFTER_STACK_CHECK; | 4794 return OSR_AFTER_STACK_CHECK; |
4798 } | 4795 } |
4799 | 4796 |
4800 | 4797 |
4801 } // namespace internal | 4798 } // namespace internal |
4802 } // namespace v8 | 4799 } // namespace v8 |
4803 | 4800 |
4804 #endif // V8_TARGET_ARCH_X64 | 4801 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |