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