| 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 1316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1327 } | 1327 } |
| 1328 } | 1328 } |
| 1329 | 1329 |
| 1330 | 1330 |
| 1331 void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy, | 1331 void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy, |
| 1332 TypeofMode typeof_mode) { | 1332 TypeofMode typeof_mode) { |
| 1333 Variable* var = proxy->var(); | 1333 Variable* var = proxy->var(); |
| 1334 DCHECK(var->IsUnallocatedOrGlobalSlot() || | 1334 DCHECK(var->IsUnallocatedOrGlobalSlot() || |
| 1335 (var->IsLookupSlot() && var->mode() == DYNAMIC_GLOBAL)); | 1335 (var->IsLookupSlot() && var->mode() == DYNAMIC_GLOBAL)); |
| 1336 __ Move(LoadDescriptor::NameRegister(), var->name()); | 1336 __ Move(LoadDescriptor::NameRegister(), var->name()); |
| 1337 __ LoadGlobalObject(LoadDescriptor::ReceiverRegister()); | 1337 __ movp(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand()); |
| 1338 __ Move(LoadDescriptor::SlotRegister(), | 1338 __ Move(LoadDescriptor::SlotRegister(), |
| 1339 SmiFromSlot(proxy->VariableFeedbackSlot())); | 1339 SmiFromSlot(proxy->VariableFeedbackSlot())); |
| 1340 CallLoadIC(typeof_mode); | 1340 CallLoadIC(typeof_mode); |
| 1341 } | 1341 } |
| 1342 | 1342 |
| 1343 | 1343 |
| 1344 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy, | 1344 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy, |
| 1345 TypeofMode typeof_mode) { | 1345 TypeofMode typeof_mode) { |
| 1346 // Record position before possible IC call. | 1346 // Record position before possible IC call. |
| 1347 SetExpressionPosition(proxy); | 1347 SetExpressionPosition(proxy); |
| (...skipping 765 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2113 Label allocate, done_allocate; | 2113 Label allocate, done_allocate; |
| 2114 | 2114 |
| 2115 __ Allocate(JSIteratorResult::kSize, rax, rcx, rdx, &allocate, TAG_OBJECT); | 2115 __ Allocate(JSIteratorResult::kSize, rax, rcx, rdx, &allocate, TAG_OBJECT); |
| 2116 __ jmp(&done_allocate, Label::kNear); | 2116 __ jmp(&done_allocate, Label::kNear); |
| 2117 | 2117 |
| 2118 __ bind(&allocate); | 2118 __ bind(&allocate); |
| 2119 __ Push(Smi::FromInt(JSIteratorResult::kSize)); | 2119 __ Push(Smi::FromInt(JSIteratorResult::kSize)); |
| 2120 __ CallRuntime(Runtime::kAllocateInNewSpace, 1); | 2120 __ CallRuntime(Runtime::kAllocateInNewSpace, 1); |
| 2121 | 2121 |
| 2122 __ bind(&done_allocate); | 2122 __ bind(&done_allocate); |
| 2123 __ LoadNativeContextSlot(Context::ITERATOR_RESULT_MAP_INDEX, rbx); | 2123 __ movp(rbx, GlobalObjectOperand()); |
| 2124 __ movp(rbx, FieldOperand(rbx, JSGlobalObject::kNativeContextOffset)); |
| 2125 __ movp(rbx, ContextOperand(rbx, Context::ITERATOR_RESULT_MAP_INDEX)); |
| 2124 __ movp(FieldOperand(rax, HeapObject::kMapOffset), rbx); | 2126 __ movp(FieldOperand(rax, HeapObject::kMapOffset), rbx); |
| 2125 __ LoadRoot(rbx, Heap::kEmptyFixedArrayRootIndex); | 2127 __ LoadRoot(rbx, Heap::kEmptyFixedArrayRootIndex); |
| 2126 __ movp(FieldOperand(rax, JSObject::kPropertiesOffset), rbx); | 2128 __ movp(FieldOperand(rax, JSObject::kPropertiesOffset), rbx); |
| 2127 __ movp(FieldOperand(rax, JSObject::kElementsOffset), rbx); | 2129 __ movp(FieldOperand(rax, JSObject::kElementsOffset), rbx); |
| 2128 __ Pop(FieldOperand(rax, JSIteratorResult::kValueOffset)); | 2130 __ Pop(FieldOperand(rax, JSIteratorResult::kValueOffset)); |
| 2129 __ LoadRoot(FieldOperand(rax, JSIteratorResult::kDoneOffset), | 2131 __ LoadRoot(FieldOperand(rax, JSIteratorResult::kDoneOffset), |
| 2130 done ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex); | 2132 done ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex); |
| 2131 STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize); | 2133 STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize); |
| 2132 } | 2134 } |
| 2133 | 2135 |
| (...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2401 rcx, Context::SlotOffset(var->index()), rdx, rbx, kDontSaveFPRegs); | 2403 rcx, Context::SlotOffset(var->index()), rdx, rbx, kDontSaveFPRegs); |
| 2402 } | 2404 } |
| 2403 } | 2405 } |
| 2404 | 2406 |
| 2405 | 2407 |
| 2406 void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op, | 2408 void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op, |
| 2407 FeedbackVectorSlot slot) { | 2409 FeedbackVectorSlot slot) { |
| 2408 if (var->IsUnallocated()) { | 2410 if (var->IsUnallocated()) { |
| 2409 // Global var, const, or let. | 2411 // Global var, const, or let. |
| 2410 __ Move(StoreDescriptor::NameRegister(), var->name()); | 2412 __ Move(StoreDescriptor::NameRegister(), var->name()); |
| 2411 __ LoadGlobalObject(StoreDescriptor::ReceiverRegister()); | 2413 __ movp(StoreDescriptor::ReceiverRegister(), GlobalObjectOperand()); |
| 2412 EmitLoadStoreICSlot(slot); | 2414 EmitLoadStoreICSlot(slot); |
| 2413 CallStoreIC(); | 2415 CallStoreIC(); |
| 2414 | 2416 |
| 2415 } else if (var->mode() == LET && op != Token::INIT) { | 2417 } else if (var->mode() == LET && op != Token::INIT) { |
| 2416 // Non-initializing assignment to let variable needs a write barrier. | 2418 // Non-initializing assignment to let variable needs a write barrier. |
| 2417 DCHECK(!var->IsLookupSlot()); | 2419 DCHECK(!var->IsLookupSlot()); |
| 2418 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); | 2420 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
| 2419 Label assign; | 2421 Label assign; |
| 2420 MemOperand location = VarOperand(var, rcx); | 2422 MemOperand location = VarOperand(var, rcx); |
| 2421 __ movp(rdx, location); | 2423 __ movp(rdx, location); |
| (...skipping 1623 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4045 | 4047 |
| 4046 void FullCodeGenerator::EmitCreateIterResultObject(CallRuntime* expr) { | 4048 void FullCodeGenerator::EmitCreateIterResultObject(CallRuntime* expr) { |
| 4047 ZoneList<Expression*>* args = expr->arguments(); | 4049 ZoneList<Expression*>* args = expr->arguments(); |
| 4048 DCHECK_EQ(2, args->length()); | 4050 DCHECK_EQ(2, args->length()); |
| 4049 VisitForStackValue(args->at(0)); | 4051 VisitForStackValue(args->at(0)); |
| 4050 VisitForStackValue(args->at(1)); | 4052 VisitForStackValue(args->at(1)); |
| 4051 | 4053 |
| 4052 Label runtime, done; | 4054 Label runtime, done; |
| 4053 | 4055 |
| 4054 __ Allocate(JSIteratorResult::kSize, rax, rcx, rdx, &runtime, TAG_OBJECT); | 4056 __ Allocate(JSIteratorResult::kSize, rax, rcx, rdx, &runtime, TAG_OBJECT); |
| 4055 __ LoadNativeContextSlot(Context::ITERATOR_RESULT_MAP_INDEX, rbx); | 4057 __ movp(rbx, GlobalObjectOperand()); |
| 4058 __ movp(rbx, FieldOperand(rbx, JSGlobalObject::kNativeContextOffset)); |
| 4059 __ movp(rbx, ContextOperand(rbx, Context::ITERATOR_RESULT_MAP_INDEX)); |
| 4056 __ movp(FieldOperand(rax, HeapObject::kMapOffset), rbx); | 4060 __ movp(FieldOperand(rax, HeapObject::kMapOffset), rbx); |
| 4057 __ LoadRoot(rbx, Heap::kEmptyFixedArrayRootIndex); | 4061 __ LoadRoot(rbx, Heap::kEmptyFixedArrayRootIndex); |
| 4058 __ movp(FieldOperand(rax, JSObject::kPropertiesOffset), rbx); | 4062 __ movp(FieldOperand(rax, JSObject::kPropertiesOffset), rbx); |
| 4059 __ movp(FieldOperand(rax, JSObject::kElementsOffset), rbx); | 4063 __ movp(FieldOperand(rax, JSObject::kElementsOffset), rbx); |
| 4060 __ Pop(FieldOperand(rax, JSIteratorResult::kDoneOffset)); | 4064 __ Pop(FieldOperand(rax, JSIteratorResult::kDoneOffset)); |
| 4061 __ Pop(FieldOperand(rax, JSIteratorResult::kValueOffset)); | 4065 __ Pop(FieldOperand(rax, JSIteratorResult::kValueOffset)); |
| 4062 STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize); | 4066 STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize); |
| 4063 __ jmp(&done, Label::kNear); | 4067 __ jmp(&done, Label::kNear); |
| 4064 | 4068 |
| 4065 __ bind(&runtime); | 4069 __ bind(&runtime); |
| 4066 __ CallRuntime(Runtime::kCreateIterResultObject, 2); | 4070 __ CallRuntime(Runtime::kCreateIterResultObject, 2); |
| 4067 | 4071 |
| 4068 __ bind(&done); | 4072 __ bind(&done); |
| 4069 context()->Plug(rax); | 4073 context()->Plug(rax); |
| 4070 } | 4074 } |
| 4071 | 4075 |
| 4072 | 4076 |
| 4073 void FullCodeGenerator::EmitLoadJSRuntimeFunction(CallRuntime* expr) { | 4077 void FullCodeGenerator::EmitLoadJSRuntimeFunction(CallRuntime* expr) { |
| 4074 // Push the builtins object as receiver. | 4078 // Push the builtins object as receiver. |
| 4075 __ PushRoot(Heap::kUndefinedValueRootIndex); | 4079 __ PushRoot(Heap::kUndefinedValueRootIndex); |
| 4076 | 4080 |
| 4077 __ LoadNativeContextSlot(expr->context_index(), rax); | 4081 __ movp(rax, GlobalObjectOperand()); |
| 4082 __ movp(rax, FieldOperand(rax, JSGlobalObject::kNativeContextOffset)); |
| 4083 __ movp(rax, ContextOperand(rax, expr->context_index())); |
| 4078 } | 4084 } |
| 4079 | 4085 |
| 4080 | 4086 |
| 4081 void FullCodeGenerator::EmitCallJSRuntimeFunction(CallRuntime* expr) { | 4087 void FullCodeGenerator::EmitCallJSRuntimeFunction(CallRuntime* expr) { |
| 4082 ZoneList<Expression*>* args = expr->arguments(); | 4088 ZoneList<Expression*>* args = expr->arguments(); |
| 4083 int arg_count = args->length(); | 4089 int arg_count = args->length(); |
| 4084 | 4090 |
| 4085 SetCallPosition(expr, arg_count); | 4091 SetCallPosition(expr, arg_count); |
| 4086 __ movp(rdi, Operand(rsp, (arg_count + 1) * kPointerSize)); | 4092 __ movp(rdi, Operand(rsp, (arg_count + 1) * kPointerSize)); |
| 4087 __ Set(rax, arg_count); | 4093 __ Set(rax, arg_count); |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4157 : Runtime::kDeleteProperty_Sloppy, | 4163 : Runtime::kDeleteProperty_Sloppy, |
| 4158 2); | 4164 2); |
| 4159 context()->Plug(rax); | 4165 context()->Plug(rax); |
| 4160 } else if (proxy != NULL) { | 4166 } else if (proxy != NULL) { |
| 4161 Variable* var = proxy->var(); | 4167 Variable* var = proxy->var(); |
| 4162 // Delete of an unqualified identifier is disallowed in strict mode but | 4168 // Delete of an unqualified identifier is disallowed in strict mode but |
| 4163 // "delete this" is allowed. | 4169 // "delete this" is allowed. |
| 4164 bool is_this = var->HasThisName(isolate()); | 4170 bool is_this = var->HasThisName(isolate()); |
| 4165 DCHECK(is_sloppy(language_mode()) || is_this); | 4171 DCHECK(is_sloppy(language_mode()) || is_this); |
| 4166 if (var->IsUnallocatedOrGlobalSlot()) { | 4172 if (var->IsUnallocatedOrGlobalSlot()) { |
| 4167 __ movp(rax, NativeContextOperand()); | 4173 __ Push(GlobalObjectOperand()); |
| 4168 __ Push(ContextOperand(rax, Context::EXTENSION_INDEX)); | |
| 4169 __ Push(var->name()); | 4174 __ Push(var->name()); |
| 4170 __ CallRuntime(Runtime::kDeleteProperty_Sloppy, 2); | 4175 __ CallRuntime(Runtime::kDeleteProperty_Sloppy, 2); |
| 4171 context()->Plug(rax); | 4176 context()->Plug(rax); |
| 4172 } else if (var->IsStackAllocated() || var->IsContextSlot()) { | 4177 } else if (var->IsStackAllocated() || var->IsContextSlot()) { |
| 4173 // Result of deleting non-global variables is false. 'this' is | 4178 // Result of deleting non-global variables is false. 'this' is |
| 4174 // not really a variable, though we implement it as one. The | 4179 // not really a variable, though we implement it as one. The |
| 4175 // subexpression does not have side effects. | 4180 // subexpression does not have side effects. |
| 4176 context()->Plug(is_this); | 4181 context()->Plug(is_this); |
| 4177 } else { | 4182 } else { |
| 4178 // Non-global variable. Call the runtime to try to delete from the | 4183 // Non-global variable. Call the runtime to try to delete from the |
| (...skipping 541 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4720 } | 4725 } |
| 4721 | 4726 |
| 4722 | 4727 |
| 4723 void FullCodeGenerator::PushFunctionArgumentForContextAllocation() { | 4728 void FullCodeGenerator::PushFunctionArgumentForContextAllocation() { |
| 4724 Scope* closure_scope = scope()->ClosureScope(); | 4729 Scope* closure_scope = scope()->ClosureScope(); |
| 4725 if (closure_scope->is_script_scope() || | 4730 if (closure_scope->is_script_scope() || |
| 4726 closure_scope->is_module_scope()) { | 4731 closure_scope->is_module_scope()) { |
| 4727 // Contexts nested in the native context have a canonical empty function | 4732 // Contexts nested in the native context have a canonical empty function |
| 4728 // as their closure, not the anonymous closure containing the global | 4733 // as their closure, not the anonymous closure containing the global |
| 4729 // code. | 4734 // code. |
| 4730 __ movp(rax, NativeContextOperand()); | 4735 __ movp(rax, GlobalObjectOperand()); |
| 4736 __ movp(rax, FieldOperand(rax, JSGlobalObject::kNativeContextOffset)); |
| 4731 __ Push(ContextOperand(rax, Context::CLOSURE_INDEX)); | 4737 __ Push(ContextOperand(rax, Context::CLOSURE_INDEX)); |
| 4732 } else if (closure_scope->is_eval_scope()) { | 4738 } else if (closure_scope->is_eval_scope()) { |
| 4733 // Contexts created by a call to eval have the same closure as the | 4739 // Contexts created by a call to eval have the same closure as the |
| 4734 // context calling eval, not the anonymous closure containing the eval | 4740 // context calling eval, not the anonymous closure containing the eval |
| 4735 // code. Fetch it from the context. | 4741 // code. Fetch it from the context. |
| 4736 __ Push(ContextOperand(rsi, Context::CLOSURE_INDEX)); | 4742 __ Push(ContextOperand(rsi, Context::CLOSURE_INDEX)); |
| 4737 } else { | 4743 } else { |
| 4738 DCHECK(closure_scope->is_function_scope()); | 4744 DCHECK(closure_scope->is_function_scope()); |
| 4739 __ Push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); | 4745 __ Push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); |
| 4740 } | 4746 } |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4881 Assembler::target_address_at(call_target_address, | 4887 Assembler::target_address_at(call_target_address, |
| 4882 unoptimized_code)); | 4888 unoptimized_code)); |
| 4883 return OSR_AFTER_STACK_CHECK; | 4889 return OSR_AFTER_STACK_CHECK; |
| 4884 } | 4890 } |
| 4885 | 4891 |
| 4886 | 4892 |
| 4887 } // namespace internal | 4893 } // namespace internal |
| 4888 } // namespace v8 | 4894 } // namespace v8 |
| 4889 | 4895 |
| 4890 #endif // V8_TARGET_ARCH_X64 | 4896 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |